package com.atguigu.bigdata.scala.chapter07

import scala.io.{BufferedSource, Source}

object Scala11_Collection_WordCount {

    def main(args: Array[String]): Unit = {

        // TODO - WordCount
        // 大数据业务中离不开 : WordCount
        // WordCount => Word + Count => 一个单词出现的次数（频率）
        // 广告点击数量 => 广告（Word） + 点击（Count）
        // 用户访问数量 => 用户访问（Word） + 访问（Count）
        // 热门商品    => 商品（Word） + 热门（Count）

        // TODO 需求：从文件中读取数据，统计文件中单词出现的次数，取前3名(出现次数的降序后的前3名)

        // TODO 1. 读取文件中的数据, 加载到内存中，形成集合数据
        // line, line, line
        val source: BufferedSource = Source.fromFile("data/word.txt")
        val list: List[String] = source.getLines().toList
        source.close()
        println("原始数据的集合 = " + list)
        // TODO 2. 将读取的数据拆分成一个一个的单词
        //         将整体拆分成个体使用的操作，称之为扁平化
        // line => word, word, word
        val words = list.flatMap(
            line => line.split(" ")
        )
        println("分解单词后的集合 = " + words)
        // TODO 3. 将数据根据单词进行分组：相同的单词放置在一个组中
        //         分组后，数据集合的类型为Map类型
        // word => List(word, word, word)
        val wordGroup = words.groupBy( word=>word )
        println("单词分组后的集合 = " + wordGroup)

        // TODO 4. 将分组后的数据进行转换，得到单词的数量
        // word => 3
        // (word, list) => (word, count)
        // A => B
        // map转换，只是转换数据，集合类型不会转换，所以集合还是Map类型
        val wordCount = wordGroup.map(
            t => {
                val word = t._1
                val list = t._2
                (word, list.size)
            }
        )
        println("分组统计后的集合 = " + wordCount)

        // TODO 5. 将结果进行排序（数量的降序），取前3名
        // word1 => 4, word2 => 3, word3 => 2, word4 => 1
        // word1 => 4, word2 => 3, word3 => 2
        // map类型的集合没有排序功能，如果想要排序，那么就需要将Map集合转换为能排序的集合
        val wordCounts: List[(String, Int)] = wordCount.toList
        val sortedWordCounts = wordCounts.sortBy(t=>t._2)(Ordering.Int.reverse)
        println("排序后的集合 = " + sortedWordCounts)
        val top3 = sortedWordCounts.take(3)
        println("前三的集合 = " + top3)
        // TODO 6. 将结果打印在控制台上
        // word1 => 4, word2 => 3, word3 => 2
        println("最后的执行结果-------------------------")
        top3.foreach(println)

    }
}
